package dao;

import dao.exception.AlreadyEntityExistsException;
import dao.exception.NotEntityFoundException;
import entity.Entidad;
import java.util.List;
import javax.persistence.EntityExistsException;
import javax.persistence.EntityManager;
import javax.persistence.Query;
import javax.persistence.criteria.CriteriaQuery;

public abstract class AbstractDataAccessObject<E extends Entidad>{
    
    private Class<E> EntityClass; 
    
    public AbstractDataAccessObject(Class<E> entityClass){
        this.EntityClass = entityClass;
    }
    
    public E create(E entity, EntityManager em) throws AlreadyEntityExistsException{
        try{
            em.persist(entity);
            return entity;
        }catch(EntityExistsException ex){
            throw new AlreadyEntityExistsException();
        }
    }
    
    public void update(E entity, EntityManager em){
        em.merge(entity);
    }
    
    public void delete(E entity, EntityManager em) throws NotEntityFoundException{
        if(entity == null)
            throw new NotEntityFoundException();
        em.remove(entity);
    }
    
    public E findById(int id, EntityManager em) throws NotEntityFoundException{
       E entidad = em.find(EntityClass, id);
       if(entidad == null){
           throw new NotEntityFoundException();
       }
       return entidad;
    }
    
    public List<E> findAll(EntityManager em){
        CriteriaQuery criteriaQuery = em.getCriteriaBuilder().createQuery();
        criteriaQuery.select(criteriaQuery.from(EntityClass));
        return em.createQuery(criteriaQuery).getResultList();
    }
    
    public List<E> findRange(int begin, int end, EntityManager em){
        CriteriaQuery criteriaQuery = em.getCriteriaBuilder().createQuery();
        criteriaQuery.select(criteriaQuery.from(EntityClass));
        Query query = em.createQuery(criteriaQuery);
        query.setMaxResults(end-begin);
        query.setFirstResult(begin);
        return em.createQuery(criteriaQuery).getResultList();
    }
}
